import os
import sys
import time
from multiprocessing import Process
from PySide2.QtGui import QIcon, QPixmap, QImage, QColor
from PySide2.QtCore import QPoint, QThread, QTimer, Qt, QEvent
from PySide2.QtWidgets import QWidget, QLabel, QSizePolicy, QSystemTrayIcon, QPushButton, QMenu, QVBoxLayout, QHBoxLayout, QLineEdit, QComboBox, QSpinBox, QCheckBox, QTextEdit, QApplication, QColorDialog
from PySide2.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineSettings

icon_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'static', 'favicon.ico')

class TitleBar(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        height = 32

        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setFixedHeight(height)
        self.setMinimumWidth(height)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.labelIcon = QLabel()
        self.labelIcon.setScaledContents(False)
        self.labelIcon.setObjectName('labelIcon')
        self.labelIcon.setPixmap(QPixmap(icon_path).scaled(height, height, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        self.labelIcon.setFixedSize(height, height)
        self.labelIcon.setCursor(Qt.OpenHandCursor)
        self.labelTitle = QLabel()
        self.labelTitle.setObjectName('labelTitle')
        self.labelTitle.setFixedHeight(height)
        self.labelTitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.labelTitle.setCursor(Qt.OpenHandCursor)
        self.buttonMinimize = QPushButton()
        self.buttonMinimize.setObjectName('buttonMinimize')
        self.buttonMinimize.setFixedSize(16, 16)
        self.buttonMinimize.setCursor(Qt.PointingHandCursor)
        self.buttonMaximize = QPushButton()
        self.buttonMaximize.setObjectName('buttonMaximize')
        self.buttonMaximize.setFixedSize(16, 16)
        self.buttonMaximize.setCursor(Qt.PointingHandCursor)
        self.buttonClose = QPushButton()
        self.buttonClose.setObjectName('buttonClose')
        self.buttonClose.setFixedSize(16, 16)
        self.buttonClose.setCursor(Qt.PointingHandCursor)

        self.setStyleSheet('''
            QWidget {
                padding: 0px;
            }
            QLabel#labelIcon {
                background-color: transparent;
                border: none;
                border-radius: 8px;
            }
            QLabel#labelTitle {
                font-family: Arial, sans-serif;
                background-color: transparent;
                color: #bbb;
                font-size: 14px;
                border-radius: 8px;
            }
            QPushButton#buttonMinimize {
                background-color: #BD9719;
                border: none;
                border-radius: 8px;
            }
            QPushButton#buttonMinimize:hover {
                background-color: #CDA753;
            }
            QPushButton#buttonMaximize {
                background-color: #30853D;
                border: none;
                border-radius: 8px;
            }
            QPushButton#buttonMaximize:hover {
                background-color: #41A94F;
            }
            QPushButton#buttonClose {
                background-color: #C51123;
                border: none;
                border-radius: 8px;
            }
            QPushButton#buttonClose:hover {
                background-color: #F96C76;
            }
        ''')

        self.layout.addWidget(self.labelIcon)
        self.layout.addWidget(self.labelTitle)
        self.layout.addWidget(self.buttonMinimize, alignment=Qt.AlignRight)
        self.layout.addWidget(self.buttonMaximize, alignment=Qt.AlignRight)
        self.layout.addWidget(self.buttonClose, alignment=Qt.AlignRight)

        self.buttonMinimize.clicked.connect(self.onMinimize)
        self.buttonMaximize.clicked.connect(self.onMaximize)
        self.buttonClose.clicked.connect(self.onClose)

        self.setLayout(self.layout)

    def showAll(self):
        self.labelTitle.show()
        self.buttonMinimize.show()
        self.buttonMaximize.show()
        self.buttonClose.show()

    def hideAll(self):
        self.labelTitle.hide()
        self.buttonMinimize.hide()
        self.buttonMaximize.hide()
        self.buttonClose.hide()

    def onMinimize(self):
        self.parent().showMinimized()

    def onMaximize(self):
        if (self.parent().windowState() == Qt.WindowMaximized):
            self.parent().showNormal()
        else:
            self.parent().showMaximized()

    def onClose(self):
        self.parent().close()

class ChatApp(QWidget):
    def __init__(self, url, parent=None):
        super().__init__(parent)

        self.setWindowIcon(QIcon(icon_path))
        self.setWindowTitle('Chat App')

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint)

        self.resize(768, 512)

        self.webView = QWebEngineView()
        self.webPage = QWebEnginePage()
        self.webPage.settings().setDefaultTextEncoding('utf-8')
        self.webPage.settings().setAttribute(QWebEngineSettings.ShowScrollBars, False)
        self.webPage.setBackgroundColor(Qt.transparent)
        self.webPage.setUrl(url)
        self.webView.setPage(self.webPage)

        self.titleBar = TitleBar()
        self.titleBar.installEventFilter(self)
        self.titleBar.labelIcon.installEventFilter(self)
        self.titleBar.setMouseTracking(True)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.titleBar)
        layout.addWidget(self.webView)
        self.setLayout(layout)

        self.titleBar.setFocusPolicy(Qt.NoFocus)
        self.webView.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.webView.setFocusPolicy(Qt.StrongFocus)
        self.webView.setFocus()

        self.isTitleBarPressed = False
        self.isTitleBarMoved = False
        self.oldSize = None
        self.offset = QPoint()

    def eventFilter(self, watched, event):
        if watched == self.titleBar.labelIcon:
            if event.type() == QEvent.MouseButtonPress:
                if event.button() == Qt.LeftButton:
                    self.offset = event.pos()
                    self.offsetGlobal = event.globalPos()
                    self.isTitleBarPressed = True
                    self.isTitleBarMoved = False
                    self.titleBar.labelIcon.setCursor(Qt.ClosedHandCursor)
                    return True
            elif event.type() == QEvent.MouseMove:
                if self.isTitleBarPressed:
                    self.isTitleBarMoved = True
                    self.move(event.globalPos() - self.offset)
                    return True
            elif event.type() == QEvent.MouseButtonRelease:
                if self.isTitleBarPressed:
                    self.isTitleBarPressed = False
                    self.titleBar.labelIcon.setCursor(Qt.OpenHandCursor)
                    if not self.isTitleBarMoved:
                        if self.oldSize is not None:
                            self.resize(self.oldSize[0], self.oldSize[1])
                            self.titleBar.showAll()
                            self.oldSize = None
                        else:
                            self.oldSize = (self.width(), self.height())
                            self.titleBar.hideAll()
                            self.resize(self.titleBar.labelIcon.width(), self.titleBar.labelIcon.height())
                    return True
        elif watched == self.titleBar:
            if event.type() == QEvent.MouseButtonPress:
                if event.button() == Qt.LeftButton:
                    self.offset = event.pos()
                    self.isTitleBarPressed = True
                    self.isTitleBarMoved = False
                    self.titleBar.labelTitle.setCursor(Qt.ClosedHandCursor)
                    return True
            elif event.type() == QEvent.MouseMove:
                if self.isTitleBarPressed:
                    self.isTitleBarMoved = True
                    self.move(event.globalPos() - self.offset)
                    return True
            elif event.type() == QEvent.MouseButtonRelease:
                if self.isTitleBarPressed:
                    self.isTitleBarPressed = False
                    self.titleBar.labelTitle.setCursor(Qt.OpenHandCursor)
                    # if not self.isTitleBarMoved:
                    #     if self.oldSize is not None:
                    #         self.titleBar.showAll()
                    #         self.resize(self.oldSize[0], self.oldSize[1])
                    #         self.oldSize = None
                    #     else:
                    #         self.oldSize = (self.width(), self.height())
                    #         self.resize(self.width(), self.titleBar.labelIcon.height())
                    return True
        return super().eventFilter(watched, event)

def alloc_free_port():
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', 0))
    addr = s.getsockname()
    port = addr[1]
    s.close()
    return port

def check_port_ready(port):
    import requests
    try:
        requests.get('http://127.0.0.1:{}'.format(port))
        return True
    except:
        return False

def main():
    port = alloc_free_port()
    server = Process(target=start_server, args=['127.0.0.1:{}'.format(port)], daemon=True)
    server.start()
    qt_app = QApplication(sys.argv)
    while not check_port_ready(port):
        time.sleep(0.5)
    chat_app = ChatApp('http://127.0.0.1:{}'.format(port))
    chat_app.show()
    ret = qt_app.exec_()
    return ret

if __name__ == '__main__':
    main()
